/*
 * Packet.h
 *
 *  Created on: Dec 22, 2016
 *      Author: root
 */

#ifndef PACKET_H_
#define PACKET_H_

//#include <Poco/Util/Application.h>
#include <Poco/AutoPtr.h>
#include <Poco/RefCountedObject.h>
#include <Poco/Types.h>
#include <Poco/Exception.h>

#include <iostream>

using namespace Poco;

namespace util
{

enum MSG_TYPE {
	MSG_TYPE_JSONRPC = 0,
	MSG_TYPE_MAX,
};

//enum MsgFlag {
//	MSG_FLAG_JSONRPC = 0,
//	MSG_FLAG_MAX
//};

enum MSG_ERROR {
	MSG_ERROR_INVALID_TYPE = 1,
};

#pragma pack(1)
typedef struct PacketHeader
{
	UInt8 type = 0;
	UInt8 flag = 0;
	UInt16 length = 0;	//the length not include the length of header
} PacketHeader;
#pragma pack()

// Packet

class Packet : public RefCountedObject
{
public:
	typedef AutoPtr<Packet> Ptr;

	Packet()
	: _header(), _pdata(nullptr) {}
	~Packet() { if (_pdata != nullptr) delete [] _pdata; }

	Packet(Packet& packet)
	{
		_header = *packet.getHeader();
		_pdata = packet._pdata;
		packet._pdata = nullptr;
	}

	const PacketHeader* getHeader() const { return &_header; }
	char *getData() const { return _pdata; }
	std::string getDataString() const { return std::string(_pdata, _header.length - 1 - sizeof(PacketHeader)); }
//	void resetData()
//	{
//		if (_pdata != nullptr) delete [] _pdata;
//		_pdata = nullptr;
//	}
	void allocData()
	{
		allocData(_header.length - sizeof(PacketHeader));
	}

	int checkHeader(const PacketHeader *pheader, std::string& errmsg) const
	{
		UInt8 type = pheader->type;

		if (type >= MSG_TYPE_MAX)
		{
			errmsg = "invalid packet type and flag";
			return -MSG_ERROR_INVALID_TYPE;
		}

		return 0;
	}

private:
	void allocData(UInt32 length)
	{
		if (_pdata != nullptr) delete [] _pdata;
		_pdata = new char[length];
	}

	PacketHeader _header;
	char *_pdata = nullptr;
};

}	// endof namespace util

#endif /* PACKET_H_ */
